package simpledb.log;

import static simpledb.file.Page.INT_SIZE;
import simpledb.file.*;
import java.util.Iterator;

/**
 * A class that provides the ability to move through the records of the log file
 * in reverse order.<br>
 * 一个提供以相反的顺序移动日志文件记录能力的类。<br>
 * 日志迭代器，提供了在日志文件中，倒序读取日志记录的机制。主要负责读。
 * 基于前面的倒序链表的数据结构，从日志文件中一次读取日志记录。由于特殊的数据结构，顺序读的过程中，实现了日志语义上的从最近时间向前倒序地读取
 * 
 * @author Edward Sciore
 */
class LogIterator implements Iterator<BasicLogRecord> {
  private Block blk;
  private Page pg = new Page();
  private int currentrec;

  /**
   * Creates an iterator for the records in the log file, positioned after the
   * last log record. This constructor is called exclusively by
   * {@link LogMgr#iterator()}.<br>
   * 为日志文件中记录创建迭代器，位于最后一条日志记录之后。 此构造函数由{@link LogMgr#iterator()}唯一调用。
   */
  LogIterator(Block blk) {
    this.blk = blk;
    pg.read(blk);
    currentrec = pg.getInt(LogMgr.LAST_POS);
  }

  /**
   * Determines if the current log record is the earliest record in the log
   * file.<br>
   * 确定当前日志记录是否为日志文件中最早的记录。
   * 
   * @return true if there is an earlier record
   */
  public boolean hasNext() {
    return currentrec > 0 || blk.number() > 0;
  }

  /**
   * Moves to the next log record in reverse order. If the current log record is
   * the earliest in its block, then the method moves to the next oldest block,
   * and returns the log record from there.<br>
   * 以相反的顺序移动到下一个日志记录。 如果当前日志记录是其块中最早的，则该方法移动到下一个最旧的块，并从那里返回日志记录。
   * 
   * @return the next earliest log record
   */
  public BasicLogRecord next() {
    if (currentrec == 0)
      moveToNextBlock();
    currentrec = pg.getInt(currentrec);
    return new BasicLogRecord(pg, currentrec + INT_SIZE);
  }

  public void remove() {
    throw new UnsupportedOperationException();
  }

  /**
   * Moves to the next log block in reverse order, and positions it after the
   * last record in that block.<br>
   * 以相反的顺序移动到下一个日志块，并将其定位在该块中的最后一个记录之后。
   */
  private void moveToNextBlock() {
    blk = new Block(blk.fileName(), blk.number() - 1);
    pg.read(blk);
    currentrec = pg.getInt(LogMgr.LAST_POS);
  }
}
